﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO ;
using System.Text.RegularExpressions;
using EnvDTE80 ;
using System.Windows.Forms;
using EnvDTE;

namespace CodeCommentAnalyser
{
    /// <summary>
    /// come
    /// </summary>
    public struct CommentCount
    {
        public string ProjectName
        {
            get;
            set;
        }
        public string FileName
        {
            get;
            set;
        }
        
        public int ThreeSlashComment
        {
            get;
            set;
        }
        public int LinesInFile
        {
            get;
            set;
        }
        public int GlobalComment
        {
            get;
            set;
        }
        public int TotalComment
        {
            get { return GlobalComment + ThreeSlashComment; }
           
        }
        public int CommentRatio
        {
            get { return (TotalComment  > 0) ? (LinesInFile / TotalComment):0 ; }
           
        }
        

    };
    /// <summary>
    /// 
    /// </summary>
    public static class CsComments
    {
        readonly static string CONST_ThreeSlash = "///";
        readonly static string CONST_CsExtension = ".cs";
        static Regex regExComment = new Regex("[^/* */$]", RegexOptions.Compiled);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="FilePath"></param>
        /// <returns></returns>
        internal static Tuple<bool, CommentCount> GetLineCount(string FilePath,string FileName)
        {
            CommentCount commCount = new CommentCount();

            try
            {

                String[] lstLinesofCode = null;
                if (File.Exists(FilePath))
                {
                    lstLinesofCode = File.ReadAllLines(FilePath);

                    if (lstLinesofCode != null && lstLinesofCode.Length > 0)
                    {
                        commCount.LinesInFile = lstLinesofCode.Length;
                        IEnumerable<string> x = lstLinesofCode.Where(s => s.Contains(CONST_ThreeSlash));
                        if (x != null)
                        {
                           
                            commCount.ThreeSlashComment = x.Count();
                            commCount.FileName = FileName;
                        }
                         
                        return new Tuple<bool, CommentCount>(true, commCount);
                    }
                }
            }
            catch(Exception ex)
            {
                return new Tuple<bool, CommentCount>(false, commCount);
            }
            return new Tuple<bool, CommentCount>(false, commCount);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="CurrentAppObject"></param>
        public static void GetCommentDetails(DTE2 CurrentAppObject)
        {
            MessageBox.Show("Anlayzing Project(s) !");
            MessageBox.Show("Project count : " + CurrentAppObject.Solution.Projects.Count.ToString());
            List<CommentCount> lstProjComments = new List<CommentCount>(); 
            foreach (EnvDTE.Project proj in CurrentAppObject.Solution.Projects)
            {
                CommentCount projComm = new CommentCount();
                projComm.ProjectName = proj.Name;
                lstProjComments.Add(projComm); 
                string strProjPath = null;
                if (string.IsNullOrWhiteSpace(proj.FullName))
                {
                    strProjPath = System.IO.Path.GetFullPath(proj.Name);
                }
                else
                {

                    strProjPath = proj.FullName;
                }
                if (proj == null || proj.ProjectItems == null)
                    continue;
                

                GetAllProjects(lstProjComments, proj);
                
            }
            CommentCount TotComm =   new CommentCount
                         {
                             ProjectName = "Total : ",
            ThreeSlashComment = (from p in lstProjComments select p.ThreeSlashComment).Sum(),
            GlobalComment = (from p in lstProjComments select p.GlobalComment).Sum(),
            LinesInFile = (from p in lstProjComments select p.LinesInFile).Sum()
        };
            lstProjComments.Add(TotComm );
           /* var subTot = from p in lstProjComments

                         group p by p.FileName into g
                         select new CommentCount
                         {
                             
                             //ProjectName =  g.First (p=> p.ProjectName ), 
                             ThreeSlashComment =  g.Sum (p => p.ThreeSlashComment),
                             //ThreeSlashComment 
                             GlobalComment = g.Sum(p => p.GlobalComment),
                             LinesInFile = g.Sum(p => p.LinesInFile)

                         };
            lstProjComments.AddRange(subTot);*/
            CommentsDetail frmCd = new CommentsDetail();
            frmCd.ListProjComments = lstProjComments;
            frmCd.ShowGrid();
           
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="lstProjComments"></param>
        /// <param name="proj"></param>
        private static void GetAllProjects(List<CommentCount> lstProjComments, EnvDTE.Project proj)
        {
            foreach (EnvDTE.ProjectItem projItem in proj.ProjectItems)
            {
                if (projItem  == null )
                    break;
                string IndivFilePath;
                try
                {
                    IndivFilePath =  System.IO.Path.GetFullPath(projItem.Name);
                }
                catch
                
                {
                    continue ;
                }
                if (IndivFilePath.EndsWith(CONST_CsExtension, StringComparison.OrdinalIgnoreCase))
                    GetProjectComments(lstProjComments, projItem);
                else
                {
                        //if (projItem.SubProject != null)
                        //    MessageBox.Show(projItem.SubProject.Name);
                        if ((projItem.SubProject == null) || (projItem.SubProject.ProjectItems == null) )
                    
                            continue ;
                        CommentCount subprojComm = new CommentCount();
                        subprojComm.ProjectName = projItem.SubProject.Name;
                        lstProjComments.Add(subprojComm); 
                    GetAllProjects(lstProjComments , projItem.SubProject  ); 
                        
                 } 
                
               
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="lstProjComments"></param>
        /// <param name="projItem"></param>
        private static void GetProjectComments(List<CommentCount> lstProjComments, EnvDTE.ProjectItem projItem)
        {
                /*  CodeElements elts = projItem.FileCodeModel.CodeElements;
                  foreach (CodeElement ce in elts)
                  {
                      ce.Kind ==  vsCMElement.vsCMElementOther
                  }*/
            //MessageBox.Show(projItem.Kind  ); 
            string IndivFilePath;
            try
            {
                 IndivFilePath = projItem.FileNames[0];
            }
            catch 
            {
                return;
            }
           
                // MessageBox.Show(IndivFilePath);
                Tuple<bool, CommentCount> tupComm = GetLineCount(IndivFilePath,projItem.Name  );
                if (tupComm.Item1)
                {
                    lstProjComments.Add(tupComm.Item2);
                    //MessageBox.Show(tupComm.Item2.ThreeSlashComment.ToString());
                }
           
        }

    }
}